package com.sihai.core;

import java.io.Serializable;
import java.util.Collection;

/**
 * <code>DataAccessor</code> interface for database access
 */
public interface DataAccessor {

	/**
	 * load entity
	 * 
	 * @param type entity type
	 * @param id entity id
	 * @return entity
	 */
	<T> T load(Class<T> type, Serializable id);

	/**
	 * get entity
	 * 
	 * @param type entity type
	 * @param id entity id
	 * @return entity
	 */
	<T> T get(Class<T> type, Serializable id);

	/**
	 * save entity
	 * 
	 * @param entity entity
	 * @return id
	 */
	Serializable save(Object entity);

	/**
	 * update entity
	 * 
	 * @param entity entity
	 */
	void update(Object entity);

	/**
	 * save or update an entity based on entity state
	 * 
	 * @param entity entity
	 */
	void saveOrUpdate(Object entity);

	/**
	 * save or update a collection of entity
	 * 
	 * @param entities collection of entities
	 */
	void saveOrUpdateAll(Collection<?> entities);

	/**
	 * delete an entity
	 * 
	 * @param entity entity
	 */
	void delete(Object entity);

	/**
	 * refresh an entity
	 * 
	 * @param entity entity
	 */
	void refresh(Object entity);

	/**
	 * batch update
	 * 
	 * @param creator {@link QueryCreator}
	 * @return affect rows
	 */
	int batchUpdate(QueryCreator creator);

	/**
	 * find unique entity
	 * 
	 * @param type query return type
	 * @param creator {@link QueryCreator}
	 * @return finded entity or null. if more than one entity is founded,exception will throw
	 */
	<T> T findUnique(Class<T> type, QueryCreator creator);

	/**
	 * find unique entity
	 * 
	 * @param type query return type
	 * @param creator {@link CriteriaCreator}
	 * @return finded entity or null. if more than one entity is founded,exception will throw
	 */
	<T> T findUnique(Class<T> type, CriteriaCreator creator);

	/**
	 * find entity list by hql
	 * 
	 * @param type query return type
	 * @param hql Hibernate HQL
	 * @param values the values of param. if no param pass null.
	 * @param limit {@link Limit}
	 * @param sorter {@link Sorter}
	 * @return list of entity
	 */
	<T> LimitedList<T> findByHql(Class<T> type, String hql, Object[] values, Limit limit, Sorter sorter);

	/**
	 * find entity list by hql
	 * 
	 * @param type query return type
	 * @param hql Hibernate HQL
	 * @param values the values of param. if no param pass null.
	 * @param limit {@link Limit}
	 * @param sorter {@link Sorter}
	 * @return list of entity
	 */
	<T> LimitedList<T> findBySafeHql(Class<T> type, String hql, Object[] values, Limit limit, Sorter sorter);

	/**
	 * find entity list by {@link QueryCreator}
	 * 
	 * @param type query return type
	 * @param creator {@link QueryCreator}
	 * @param limit {@link Limit}
	 * @param sorter {@link Sorter}
	 * @return list of entity
	 */
	<T> LimitedList<T> findByQuery(Class<T> type, QueryCreator creator, Limit limit, Sorter sorter);

	/**
	 * find entity list by {@link QueryCreator}
	 * 
	 * @param type query return type
	 * @param creator {@link QueryCreator}
	 * @param limit {@link Limit}
	 * @param sorter {@link Sorter}
	 * @return list of entity
	 */
	<T> LimitedList<T> findBySafeQuery(Class<T> type, QueryCreator creator, Limit limit, Sorter sorter);

	/**
	 * find entity list by {@link CriteriaCreator}
	 * 
	 * @param type query return type
	 * @param creator {@link CriteriaCreator}
	 * @param limit {@link Limit}
	 * @param sorter {@link Sorter}
	 * @return list of entity
	 */
	<T> LimitedList<T> findByCriteria(Class<T> type, CriteriaCreator creator, Limit limit, Sorter sorter);

	/**
	 * find entity list by {@link CriteriaCreator}
	 * 
	 * @param type query return type
	 * @param creator {@link CriteriaCreator}
	 * @param limit {@link Limit}
	 * @param sorter {@link Sorter}
	 * @return list of entity
	 */
	<T> LimitedList<T> findBySafeCriteria(Class<T> type, CriteriaCreator creator, Limit limit, Sorter sorter);

	/**
	 * find entity list by specific class
	 * 
	 * @param type {@link Class}
	 * @param limit {@link Limit}
	 * @param sorter {@link Sorter}
	 * @return list of entity
	 */
	<T> LimitedList<T> findByClass(Class<T> type, Limit limit, Sorter sorter);

}